/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2016，所有权利保留。
 * <p>
 * 项目名：	notify-core
 * 文件名：	HttpClient.java
 * 模块说明：
 * 修改历史：
 * 2016-2-15 - zhangyanbo - 创建。
 */
package study.saas.common.util.http;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Map.Entry;

/**
 * @author zhangyanbo
 */
public class HttpClient {
    protected int connectTimeout = 30000;
    protected int readTimeout = 30000;

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    public String post(String url, String body, Map<String, String> headers) throws Exception {
        return getResult(url, body, "POST", headers);
    }

    public String post(String url, String body, Map<String, String> params,
                       Map<String, String> headers) throws Exception {
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        return getResult(url, body, "POST", headers);
    }

    public String put(String url, String body, Map<String, String> headers) throws Exception {
        return getResult(url, body, "PUT", headers);
    }

    public String put(String url, String body, Map<String, String> params,
                      Map<String, String> headers) throws Exception {
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        return getResult(url, body, "PUT", headers);
    }

    public String delete(String url, String body, Map<String, String> headers) throws Exception {
        return getResult(url, body, "DELETE", headers);
    }

    public String delete(String url, String body, Map<String, String> params,
                         Map<String, String> headers) throws Exception {
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        return getResult(url, body, "DELETE", headers);
    }

    public String get(String url, Map<String, String> params, Map<String, String> headers)
            throws Exception {
        String paramString = getUrlParamsByMap(params);
        if (StringUtils.isNotEmpty(paramString)) {
            url = url + "?" + paramString;
        }
        return getResult(url, null, "GET", headers);
    }

    private String getResult(String url, String body, String method, Map<String, String> headers)
            throws Exception {
        logger.info("[{}],HTTP请求[{}],header[{}],body[{}]", url, method, headers, body);
        HttpURLConnection conn = null;
        OutputStream out = null;
        try {
            conn = getConnection(new URL(url), method, headers);
            if (body != null) {
                out = conn.getOutputStream();
                out.write(body.getBytes("UTF-8"));
                out.close();
            }

            String s = getResponseBodyAsString(conn);
            logger.info("[{}],HTTP请求[{}],返回结果[{}]", url, method, s);
            if (conn.getResponseCode() >= 400) {
                logger.error("调用服务出错:{} - {}", conn.getResponseCode(), s);
            }
            return s;
        } finally {
            if (out != null) {
                out.close();
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
    }

    protected HttpURLConnection getConnection(URL url, String method, Map<String, String> headers)
            throws IOException {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod(method);
        conn.setDoInput(true);
        conn.setDoOutput(true);
        conn.setConnectTimeout(connectTimeout);
        conn.setReadTimeout(readTimeout);
        if (headers != null) {
            for (Entry<String, String> header : headers.entrySet()) {
                conn.setRequestProperty(header.getKey(), header.getValue());
            }
        }
        return conn;
    }

    protected String getResponseBodyAsString(HttpURLConnection conn) throws IOException {
        InputStream is = null;
        if (conn.getResponseCode() >= 400) {
            is = conn.getErrorStream();
        } else {
            is = conn.getInputStream();
        }

        if (is == null) {
            return null;
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            StringWriter writer = new StringWriter();

            char[] chars = new char[256];
            int count = 0;
            while ((count = reader.read(chars)) > 0) {
                writer.write(chars, 0, count);
            }

            return writer.toString();
        } finally {
            is.close();
        }
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public int getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    /**
     * 将map转换成url
     *
     * @param map
     * @return
     * @throws UnsupportedEncodingException
     */
    public static String getUrlParamsByMap(Map<String, String> map)
            throws UnsupportedEncodingException {
        if (map == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        for (Entry<String, String> entry : map.entrySet()) {
            sb.append(entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"));
            sb.append("&");
        }
        String s = sb.toString();
        if (s.endsWith("&")) {
            s = StringUtils.substringBeforeLast(s, "&");
        }
        return s;
    }
}
